package com.java.simple.study.juc.p5;

import com.java.simple.study.tool.UnsafeUtil;
import sun.misc.Unsafe;

/**
 * @author zhoujunlin
 * @date 2022年07月05日 21:31
 * @desc
 */
public class MyAtomicAccount implements Account {

    private final AtomicData atomicData;

    public MyAtomicAccount(Integer amount) {
        this.atomicData = new AtomicData(amount);
    }

    @Override
    public Integer getBalance() {
        return atomicData.getData();
    }

    @Override
    public void withdraw(Integer amount) {
        atomicData.decrease(amount);
    }

    public static void main(String[] args) {
        Account.demo(new MyAtomicAccount(10000));
        //剩余:0 cost:135 ms
    }

}


class AtomicData {
    private final int data;
    private static final Unsafe unsafe;
    private static final long DATA_OFFSET;

    static {
        unsafe = UnsafeUtil.getUnsafe();
        try {
            DATA_OFFSET = unsafe.objectFieldOffset(AtomicData.class.getDeclaredField("data"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

    public AtomicData(int data) {
        this.data = data;
    }

    public int getData() {
        return data;
    }

    public void decrease(int amount) {
        int oldValue;
        while (true) {
            oldValue = this.data;
            // cas尝试修改data
            if (unsafe.compareAndSwapInt(this, DATA_OFFSET, oldValue, oldValue - amount)) {
                break;
            }
        }
    }

}
